package sfin.swt.util;

import java.util.ResourceBundle;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;

import sfin.controller.BancoController;
import sfin.controller.CartaoController;
import sfin.controller.CategoriaController;
import sfin.controller.ConfigController;
import sfin.controller.ContaController;
import sfin.controller.LancamentoController;
import sfin.controller.SimulacaoController;
import sfin.swt.composite.AboutComposite;
import sfin.swt.composite.BancoComposite;
import sfin.swt.composite.CartaoCreditoComposite;
import sfin.swt.composite.CategoriaComposite;
import sfin.swt.composite.ConfigComposite;
import sfin.swt.composite.ContaCorrenteComposite;
import sfin.swt.composite.LancamentoComposite;
import sfin.swt.composite.ResumoFinanceiroComposite;
import sfin.swt.composite.SimulacaoComposite;

public class DialogUtil {

	private static final int DEFAULT_WIDTH = 750;
	private static final int DEFAUT_HEIGHT = 650;
	public static final int POSITION_NONE = 0;
	public static final int POSITION_1 = 2;
	public static final int POSITION_2 = 4;
	public static final int POSITION_3 = 8;
	public static final int POSITION_4 = 16;

	private ResourceBundle bundle;
	private Display display;
	private BancoController bancoController;
	private ContaController contaController;
	private CartaoController cartaoController;
	private CategoriaController categoriaController;
	private LancamentoController lancamentoController;
	private SimulacaoController simulacaoController;
	private ConfigController configController;
	
	private MessageUtil messageUtil;

	public DialogUtil(ResourceBundle bundle, Display display, MessageUtil messageUtil){
		this.bundle = bundle;
		this.display = display;
		this.messageUtil = messageUtil;
	}

	public void setBancoController(BancoController bancoController) {
		this.bancoController = bancoController;
	}

	public void setContaController(ContaController contaController) {
		this.contaController = contaController;
	}

	public void setCartaoController(CartaoController cartaoController) {
		this.cartaoController = cartaoController;
	}

	public void setCategoriaController(CategoriaController categoriaController) {
		this.categoriaController = categoriaController;
	}

	public void setLancamentoController(
			LancamentoController lancamentoController) {
		this.lancamentoController = lancamentoController;
	}


	public void setSimulacaoController(SimulacaoController simulacaoController) {
		this.simulacaoController = simulacaoController;
	}
	
	public void setConfigController(ConfigController configController) {
		this.configController = configController;
	}

	
	private Shell createDialog(String title, int leftPos, int rightPos){
		return createDialog(DEFAULT_WIDTH,DEFAUT_HEIGHT, leftPos, rightPos, title);
	}

	protected int assignPos(int x){
		switch (x) {
		case POSITION_1: return x;
		case POSITION_2: return x;
		case POSITION_3: return x;
		case POSITION_4: return x;
		case POSITION_NONE: return x;
		}
		return POSITION_1;
	}

	private Shell createDialog(int w, int h, int leftPos, int rightPos, String title){
		Shell dialog = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
		dialog.setLayout(new FillLayout());
		dialog.setSize(w,h);

		if(title != null)
			dialog.setText(bundle.getString(title));

		Monitor primary = display.getPrimaryMonitor();
		Rectangle bounds = primary.getBounds();
		Rectangle rect = dialog.getBounds();
		
		int xDivider = assignPos(leftPos);
		int yDivider = assignPos(rightPos);
		
		int x = 0;
		int y = 0;
		
		if(POSITION_NONE == xDivider){
			x= bounds.x + (bounds.width - rect.width);
		}else{
			x= bounds.x + (bounds.width - rect.width) / assignPos(leftPos);
		}
		
		if(POSITION_NONE == yDivider){
			y = bounds.y + (bounds.height - rect.height);	
		}else{
			y = bounds.y + (bounds.height - rect.height) / assignPos(rightPos);
		}
		
		dialog.setLocation(x, y);
		return dialog;
	}

	private void putDisposeListeners(Control composite, DisposeListener... listeners){
		if(composite == null || listeners == null || listeners.length == 0)
			return;

		for (int i = 0; i < listeners.length; i++) {
			composite.addDisposeListener(listeners[i]);
		}
	}
	

	public void openCategoriaDialog(DisposeListener... listeners){

		openDialog(new CompositeInstantiator() {
			@Override
			public Control instantiateIn(Shell dialog) {
				return new CategoriaComposite(dialog, bundle, categoriaController,messageUtil,SWT.NONE);
			}

			@Override
			public void onCloseDialog() {
				categoriaController.clearSelection();
			}
		}, "category.edit.title", listeners);
	}

	public void openLancamentoDialog(boolean clearSelection,DisposeListener... listeners){


		if(lancamentoController.isSaldoSelecionado()){

			messageUtil.showWarnMessage(bundle.getString("lancamento.saldo.edit.error"));			

		}else if(lancamentoController.isLancamentosFinalizados()){

			messageUtil.showWarnMessage(bundle.getString("lancamentos.end.message"));

		}else{

			if(clearSelection)
				lancamentoController.clearSelectionIndices();

			lancamentoController.loadData();

			openDialog(new CompositeInstantiator() {
				@Override
				public Control instantiateIn(Shell dialog) {
					return new LancamentoComposite(dialog, SWT.NONE, lancamentoController,bundle, messageUtil,getMe());
				}

				@Override
				public void onCloseDialog() {
				}
			}, "string.general.entry", listeners);

		}

	}

	public void openContaDialog(DisposeListener... listeners){
		openDialog(new CompositeInstantiator() {
			@Override
			public Control instantiateIn(Shell dialog) {
				return new ContaCorrenteComposite(dialog, bundle, contaController, messageUtil, SWT.NONE);
			}

			@Override
			public void onCloseDialog() {
				contaController.clearSelection();
			}
		}, "current.account.edit.title", listeners);
	}

	public void openCartaoDialog(DisposeListener... listeners){
		openDialog(new CompositeInstantiator() {
			@Override
			public Control instantiateIn(Shell dialog) {
				return new CartaoCreditoComposite(dialog, bundle, cartaoController,messageUtil, SWT.NONE);
			}

			@Override
			public void onCloseDialog() {
				cartaoController.clearSelection();				
			}
		}, "credit.card.edit.title", listeners);
	}

	public void openBancoDialog(DisposeListener... listeners){
		openDialog(new CompositeInstantiator() {
			@Override
			public Control instantiateIn(Shell dialog) {
				return new BancoComposite(dialog, bundle, bancoController, messageUtil,SWT.NONE);
			}

			@Override
			public void onCloseDialog() {
				bancoController.clearSelection();				
			}
		}, "bank.edit.title", listeners);
	}


	public void openResumoFinanceiroDialog(){
		openDialog(new CompositeInstantiator() {
			@Override
			public void onCloseDialog() {
			}

			@Override
			public Control instantiateIn(Shell dialog) {
				return new ResumoFinanceiroComposite(dialog, SWT.NONE, bundle, lancamentoController, contaController);
			}
		}, null);

	}

	public void openPreferenciasDialog(){
		openDialog(new CompositeInstantiator() {
			
			@Override
			public void onCloseDialog() {}
			
			@Override
			public Control instantiateIn(Shell dialog) {
				return new ConfigComposite(dialog, SWT.NONE, bundle, configController);
			}
		}, "menu.configuration", POSITION_1, POSITION_1, true);
	}

	public void openSimulacaoDialog(){
		openDialog(new CompositeInstantiator() {

			@Override
			public void onCloseDialog() {}

			@Override
			public Control instantiateIn(Shell dialog) {
				simulacaoController.loadData();
				return new SimulacaoComposite(dialog, SWT.NONE, simulacaoController, bundle, messageUtil);
			}
		}, "simulacao.dialog.title", POSITION_4, POSITION_1, true);
	}

	public void openDialog(CompositeInstantiator instantiator, String title, DisposeListener... listeners){
		openDialog(instantiator, title, POSITION_1, POSITION_1, true, listeners);
	}
	
	public void openDialog(CompositeInstantiator instantiator, String title, int leftPos, int rightPos, boolean pack, DisposeListener... listeners){
		Shell dialog = createDialog(title, leftPos, rightPos);
		Control composite = instantiator.instantiateIn(dialog);
		putDisposeListeners(composite, listeners);
		
		if(pack)
			dialog.pack();
		
		dialog.open();
		while (!dialog.isDisposed()) { 
			if (!display.readAndDispatch()) display.sleep(); 
		} 

		instantiator.onCloseDialog();
		composite.dispose();
	}
	
	public void openAboutDialog(final ApplicationUtil applicationUtil){
		openDialog(new CompositeInstantiator() {
			
			@Override
			public void onCloseDialog() {
			}
			@Override
			public Control instantiateIn(Shell dialog) {
				return new AboutComposite(dialog, SWT.NONE, bundle,applicationUtil);
			}
		}, null,POSITION_1,POSITION_2,false);
	}
	
	public void OpenHelpDialog(final String textFileName){
		
		openDialog(new CompositeInstantiator() {

			@Override
			public void onCloseDialog() {
			}

			@Override
			public Control instantiateIn(Shell dialog) {
				Composite composite = new Composite(dialog, SWT.NONE);
				composite.setBackground(new Color(display,247, 219, 161));
				composite.setLayout(new RowLayout());
				Label label = new Label(composite, SWT.NONE);
				label.setBackground(new Color(display,247, 219, 161));
				label.setText(ResourceUtil.getFileText(textFileName));
				label.setLayoutData(new RowData());
				return composite;
			}
		}, "string.general.help",POSITION_1, POSITION_NONE, true);
		
		
	}

	public DialogUtil getMe(){
		return this;
	}

}